﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using DomainDriver.DomainModeling.Constraints;
using DomainDriver.DomainModeling.DataProviders;
using DomainDriver.DomainModeling.DomainModels;
using DomainDriver.DomainModeling.Exceptions;
using DomainDriver.DomainModeling.Repositories;
using DomainDriver.DomainModeling.Example;
using DomainDriver.DomainModeling.Example.DomainObjects;
using DomainDriver.DomainModeling.GenericUnitTesting;
using DomainDriver.DomainModeling.GenericUnitTesting.Constraints;
using DomainDriver.DomainModeling.Queries;

namespace DomainDriver.DomainModeling.UnitTests.Constraints
{
    [TestFixture(new object[] { DataSourcePersistenceType.None })]
    [TestFixture(new object[] { DataSourcePersistenceType.File })]
    [TestFixture(new object[] { DataSourcePersistenceType.Database })]
    public class DummyDomainObjectIndexConstraintTests : IndexConstraintTestFixture<ExampleDomainModel, Guid, DummyDomainObject>
    {
        public DummyDomainObjectIndexConstraintTests(DataSourcePersistenceType persistenceType)
            : base(persistenceType)
        {
            // do nothing
        }

        protected override ExampleDomainModel CreateDomainModel(DataSourcePersistenceType persistenceType, bool buildModelWithConstraints)
        {
            ExampleDomainModel model = new ExampleDomainModel(persistenceType, buildModelWithConstraints);
            return model;
        }

        protected override int GetIndexValue(DummyDomainObject domainObject)
        {
            return domainObject.Index;
        }

        protected override DummyDomainObject CreateDomainObjectWithCorrectIndexValue()
        {
            DummyDomainObject domainObject = new DummyDomainObject();
            int correctIndexValue = IndexConstraint.GetIndexValueForObject(domainObject);
            domainObject.Index = correctIndexValue;
            domainObject.Name = domainObject.Key.ToString();
            return domainObject;
        }

        protected override DummyDomainObject CreateDomainObjectWithIncorrectIndexValue(ref bool hasIndexSetter)
        {
            hasIndexSetter = true;
            int incorrectIndexValue = -100;

            DummyDomainObject domainObject = new DummyDomainObject();
            domainObject.Index = incorrectIndexValue;
            domainObject.Name = domainObject.Key.ToString();
            return domainObject;
        }

        protected override void UpdateDomainObjectIndex(DummyDomainObject domainObject, ref bool hasIndexSetter)
        {
            hasIndexSetter = true;
            domainObject.Index += 1;
        }

        protected override void CreateMultipleObjects()
        {
            DummyDomainObject domainObject1 = CreateDomainObjectWithCorrectIndexValue();
            domainObject1.Parent = null;
            IndexedRepository.Add(domainObject1);

            DummyDomainObject domainObject2 = CreateDomainObjectWithCorrectIndexValue();
            domainObject2.Parent = null;
            IndexedRepository.Add(domainObject2);

            DummyDomainObject domainObject3 = CreateDomainObjectWithCorrectIndexValue();
            domainObject3.Parent = null;
            IndexedRepository.Add(domainObject3);

            DummyDomainObject domainObject4 = CreateDomainObjectWithCorrectIndexValue();
            domainObject4.Parent = domainObject1.Key;
            IndexedRepository.Add(domainObject4);

            DummyDomainObject domainObject5 = CreateDomainObjectWithCorrectIndexValue();
            domainObject5.Parent = domainObject1.Key;
            IndexedRepository.Add(domainObject5);

            DummyDomainObject domainObject6 = CreateDomainObjectWithCorrectIndexValue();
            domainObject6.Parent = domainObject2.Key;
            IndexedRepository.Add(domainObject6);

            m_RootLevelKeys.Add(domainObject1.Key);
            m_RootLevelKeys.Add(domainObject2.Key);
            m_RootLevelKeys.Add(domainObject3.Key);

            m_ChildrenPerRootLevelKey.Add(domainObject1.Key, 2);
            m_ChildrenPerRootLevelKey.Add(domainObject2.Key, 1);
            m_ChildrenPerRootLevelKey.Add(domainObject3.Key, 0);
        }

        protected override DummyDomainObject CreateChildObject(Guid parentDomainObjectKey)
        {
            DummyDomainObject domainObject = CreateDomainObjectWithCorrectIndexValue();
            domainObject.Parent = parentDomainObjectKey;
            return domainObject;
        }

        protected override IQuery<DummyDomainObject> GetQueryForRootObjects()
        {
            Nullable<Guid> desiredParentId = null;
            LinqQuery<DummyDomainObject> linqQuery = new LinqQuery<DummyDomainObject>((DummyDomainObject dObj) => dObj.Parent.Equals(desiredParentId));

            return linqQuery;
        }
    }
}